home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 3: CDPD 3
/
Almathera Ten on Ten - Disc 3: CDPD3.iso
/
ab20
/
unarced
/
utilities
/
emulators
/
apple][
/
jump.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-03-17
|
7KB
|
324 lines
/*
* a2, an Apple II emulator in C
* (c) Copyright 1990 by Rich Skrenta
*
* Command line interface written by Tom Markson
*
* Distribution agreement:
*
* You may freely copy or redistribute this software, so long
* as there is no profit made from its use, sale, trade or
* reproduction. You may not change this copyright notice,
* and it must be included prominently in any copy made.
*
* Send emulator related mail to: skrenta@blekko.commodore.com
* skrenta@blekko.uucp
*/
#include <stdio.h>
#include <fcntl.h>
#include "a2.h"
#define jump_check(a,b,c,d) (mem[Pc]==a && mem[Pc+1]==b && mem[Pc+2]==c && mem[Pc+3]==d)
/*
* In order to improve performance, we intercept the PC on JSR's
* and JMP's to certain locations and handled the intented function
* in C instead of letting the emulator interpret 6502.
*
* This is done for video output, to produce an acceptable scroll;
* for the boot prom, so it crashes if there is no disk in the drive;
* and for other miscellaneous routines such as WAIT for speed.
*
* In most cases the interceptor routine checks to see if the code it's
* intercepting looks like what it thinks should be there; it doesn't
* snatch the PC if the first four bytes of the routine don't match.
*/
#define I_WAIT 1 /* defeat ROM WAIT routine */
#define I_PRODOS 2 /* Prodos high level intercept */
#define I_RWTS 3 /* DOS 3.3 high-level intercept */
#define I_BELL 4 /* don't toggle C030, output a bell */
#define I_VIDOUT 5 /* speeds up scrolling tremendously */
#define I_BOOT 6 /* crash if no disk on boot */
#define I_BOOTWAIT 7 /* defeat delay loops in DOS boot */
#define I_BOOTPATCH 8 /* patch dos for fast raw access */
extern int map_to_upper;
extern unsigned char disk_ref();
set_special_jumps() {
extern int set_c0();
extern int set_writep();
mem[0x43] = 0x60; /* for ProDos boot */
jmp_tbl[0xBD00] = I_RWTS;
jmp_tbl[0xC600] = I_BOOT;
jmp_tbl[0xC680] = I_PRODOS; /* patched into boot prom below */
jmp_tbl[0x9D84] = I_BOOTPATCH; /* fast raw dos access */
jmp_tbl[0xFBD9] = I_BELL;
jmp_tbl[0xFBFD] = I_VIDOUT;
jmp_tbl[0xFCA8] = I_WAIT;
jmp_tbl[0x3A00] = I_BOOTWAIT;
mem_set[0xC0] = set_c0;
mem_set[0xC6] = set_writep; /* write protect disk prom */
#if 0
mem[0xC600] = 0; /* flag for boot interception */
mem[0xC601] = 0x20; /* disk prom magic number */
mem[0xC603] = 0x00;
mem[0xC605] = 0x03;
mem[0xC607] = 0x3C;
#endif
/*
* Patch boot rom for fake Prodos driver
*/
mem[0xC6FF] = 0x80; /* C680 is driver address */
mem[0xC6FE] = 0x1F; /* info about device */
screen_setup();
}
jump(key)
int key;
{
int i;
switch (key) {
case I_WAIT: /* FCA8 */
if (jump_check(0x38, 0x48, 0xE9, 0x01)) {
A = 0;
N = 0;
V = 0;
C = 1;
DO_RTS;
}
break;
case I_PRODOS: /* C680 */
prodos();
break;
case I_RWTS: /* BD00 */
if (jump_check(0x84, 0x48, 0x85, 0x49))
rwts();
break;
case I_BELL: /* FBD9 */
if (jump_check(0x60, 0x87, 0xD0, 0x12)) {
putchar(7);
fflush(stdout);
DO_RTS;
}
break;
case I_VIDOUT: /* FBFD */
if (jump_check(0xC9, 0xA0, 0xB0, 0xEF))
vidout();
break;
case I_BOOT: /* C600 */
if (disk[0] < 0) {
info("boot: no disk");
PCINC; /* BRK into the monitor */
push(high(Pc));
push(low(Pc));
B = 1;
push(get_status());
Pc = mem[0xFFFE] | (mem[0xFFFF] << 8);
return;
}
info("boot");
/*
* We read the second half of a 512 byte block in case we're
* booting something that depends on this being a newer boot prom
*/
drive = 0;
read_disk(0, 14, &mem[0x900]);
break;
/*
* Standard DOS 3.3 has some pretty gross delay loops in its
* boot code. The following patches defeat two of them.
* This could be dangerous; it seems to work, but DOS's original
* side effects are not maintained. Comment out the jmp_tbl assignment
* of I_BOOTWAIT above if you are distrustful.
*
* Interesting. Dos relocates the patches when it moves into higher
* memory. If you boot with a fast-booting dos that doesn't have the
* delays at 3A00, but still has them at BA00 & BD9E when it starts
* up, it will be slow if you turn off RWTS interception and use the
* raw interface. However, slow-booting real DOS that gets patched
* while it's booting will have a faster raw interface, since it
* relocated the patches...
*/
case I_BOOTWAIT: /* 3A00 */
if (jump_check(0xA2, 0x11, 0xCA, 0xD0)) {
mem[0x3A00] = 0x60; /* RTS */
if (mem[0x3D9E] == 0xA0
&& mem[0x3D9F] == 0x12
&& mem[0x3DA0] == 0x88) {
mem[0x3D9E] = 0x4C; /* JMP past it */
mem[0x3D9F] = 0xAB;
mem[0x3DA0] = 0x3D; /* gets relocated */
}
}
break;
/*
* This one is unnecessary since we do high-level RWTS interception
*/
case I_BOOTPATCH: /* 9D84 */
if (jump_check(0xAD, 0xE9, 0xB7, 0x4A)) {
if (mem[0xBA00] == 0xA2
&& mem[0xBA01] == 0x11
&& mem[0xBA02] == 0xCA) {
mem[0xBA00] = 0x60; /* RTS */
if (mem[0xBD9E] == 0xA0
&& mem[0xBD9F] == 0x12
&& mem[0xBDA0] == 0x88) {
mem[0xBD9E] = 0x4C;
mem[0xBD9F] = 0xAB;
mem[0xBDA0] = 0xBD;
}
}
}
break;
default:
fprintf(stderr, "bad jump intercept key: %d\n", key);
assert(FALSE);
}
}
static int key_clear = TRUE;
static unsigned char last_key = 0;
static unsigned char temp_key;
extern int save_flags;
unsigned char
mem_map(a)
unsigned short a;
{
switch (a) {
case 0xC000:
if (key_clear) {
fcntl (0, F_SETFL, save_flags | O_NDELAY);
if (read (0, &temp_key, 1) == 1) {
key_clear = FALSE;
if (temp_key == '\n')
temp_key = '\r';
else if (temp_key == 127)
temp_key = 8;
if (map_to_upper)
temp_key = toupper(temp_key);
last_key = temp_key | 0x80;
}
fcntl (0, F_SETFL, save_flags);
}
return(last_key);
case 0xC010:
key_clear = TRUE;
last_key &= 0x7F;
return(0); /* what should this be? */
case 0xC011:
if (bank2_enable)
return(0xFF);
return(0x00);
case 0xC012:
if (ram_read)
return(0xFF);
return(0x00);
case 0xC080: case 0xC081: case 0xC082: case 0xC083:
case 0xC088: case 0xC089: case 0xC08A: case 0xC08B:
ram_card(a);
return(0x00);
/*
* Slot 6 Disk II memory map
*/
case 0xC0E0: case 0xC0E1: case 0xC0E2: case 0xC0E3:
case 0xC0E4: case 0xC0E5: case 0xC0E6: case 0xC0E7:
case 0xC0E8: case 0xC0E9: case 0xC0EA: case 0xC0EB:
case 0xC0EC: case 0xC0ED: case 0xC0EE: case 0xC0EF:
return( disk_ref(a, 0) );
#if 0
/*
* Keep the boot prom magic number from appearing if there is
* no disk in the drive
*/
case 0xC600:
case 0xC601:
if (disk[0] < 0)
return(0);
break;
#endif
}
return(mem[a]); /* default */
}
set_c0(a, n)
unsigned short a;
unsigned char n;
{
switch (a & 0xFF) {
case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15:
case 0x16: case 0x17: case 0x18: case 0x19: case 0x1A: case 0x1B:
case 0x1C: case 0x1D: case 0x1E: case 0x1F:
key_clear = TRUE;
last_key &= 0x7F;
break;
case 0x80: case 0x81: case 0x82: case 0x83:
case 0x88: case 0x89: case 0x8A: case 0x8B:
ram_card(a);
break;
/*
* Slot 6 Disk II memory map
*/
case 0xC0E0: case 0xC0E1: case 0xC0E2: case 0xC0E3:
case 0xC0E4: case 0xC0E5: case 0xC0E6: case 0xC0E7:
case 0xC0E8: case 0xC0E9: case 0xC0EA: case 0xC0EB:
case 0xC0EC: case 0xC0ED: case 0xC0EE: case 0xC0EF:
disk_ref(a, n);
break;
default:
mem[a] = n;
}
}